/************************************************************************
* Programmer:  Philippe Gambling
*
* Course:  CSCI 4534
*
* Date:  February 20, 2009
*
* Environment:  GCC 3.2.2 running on diamond.rocks.uhcl.edu
*
* Files Included: queue_test.c, queue.c, queue.h
*
* Purpose:  To test and demonstrate the functionality of the queue library.
*
* Input:  None
*
* Preconditions:  None
*
* Output:  Pass/fail status of each test.
*
* Postconditions: None
*
***********************************************************************/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../queue.h"

#define PASS 1
#define FAIL 0
#define TRUE 1
#define FALSE 0

/*************** Unit Testing Macros ***************************************/
#define START_TEST_DEF(name) int name##_test(void) \
                            { \
                              int result = PASS; \
                              numtests++; \
                              printf("Running %s test... ", #name);
#define END_TEST_DEF if(result==PASS) { \
                        printf("PASSED\n"); \
                      } \
                      else { \
                        printf("\nFAILED\n"); \
                      } \
                      return result; \
                      }
#define RUN_TEST(name) numpassed += name##_test()
#define REPORT_FAIL() printf("\nfailed at line %d",__LINE__); result = FAIL
/***************************************************************************/

int numtests; // Total number of tests run

/******************* UNIT TEST DEFINITIONS *****************************/
START_TEST_DEF(QueueAddFront)  
  Queue q = new_Queue(sizeof(int));
  
  int i = 1;
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&i) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 1) { REPORT_FAIL(); }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&i) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 2) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&i) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 3) { REPORT_FAIL(); }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueRemoveBack)  
  Queue q = new_Queue(sizeof(int));
  
  int in = 1;
  int out = 0;
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&in) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 1) { REPORT_FAIL(); }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  if(Queue_RemoveFront(q,&out) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  if(Queue_Size(q) != 0) { REPORT_FAIL(); }
  if(in!=out) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&in) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 1) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&in) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 2) { REPORT_FAIL(); }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  if(Queue_RemoveFront(q,&out) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 1) { REPORT_FAIL(); }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  if(Queue_RemoveFront(q,&out) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 0) { REPORT_FAIL(); }
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  if(Queue_RemoveFront(q,&out) == SUCCESS) { REPORT_FAIL(); }
  
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueClear)
  Queue q = new_Queue(sizeof(float));
  
  float in = 2.3;
  int i = 0;  
  int nodesToAdd = 100;
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }

  for(i=0;i<nodesToAdd;i++)
  {
    if(Queue_AddBack(q,&in) != SUCCESS) { REPORT_FAIL(); }
  }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  if(Queue_Size(q) != nodesToAdd) { REPORT_FAIL(); }  
  if(Queue_Clear(q) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_Size(q) != 0) { REPORT_FAIL(); }
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }  
      
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueGetFront)
  Queue q = new_Queue(sizeof(int));
  int in = 1;
  int out = 3;
  
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  if(Queue_GetFront(q,&out) == SUCCESS) { REPORT_FAIL(); }
  if(out != 3) { REPORT_FAIL(); }
  if(Queue_AddBack(q,&in) != SUCCESS) { REPORT_FAIL(); }
  if(Queue_GetFront(q,&out) != SUCCESS) { REPORT_FAIL(); }
  if(in != out) { REPORT_FAIL(); }
  in++;
  if(Queue_AddBack(q,&in) != SUCCESS) { REPORT_FAIL(); }  
  if(Queue_Size(q) != 2) { REPORT_FAIL(); }
  if(Queue_GetFront(q,&out) != SUCCESS) { REPORT_FAIL(); }
  if(out != in-1) { REPORT_FAIL(); }  
  if(Queue_RemoveFront(q,&in) != SUCCESS) { REPORT_FAIL(); }  
  if(Queue_GetFront(q,&out) != SUCCESS) { REPORT_FAIL(); }  
  if(out != in+1) { REPORT_FAIL(); }    
  if(Queue_Size(q) != 1) { REPORT_FAIL(); }
  if(Queue_RemoveFront(q,&out) != SUCCESS) { REPORT_FAIL(); }  
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  if(Queue_GetFront(q,&out) == SUCCESS) { REPORT_FAIL(); }    
  if(out != 2) { REPORT_FAIL(); }
  
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueIterate)
  Queue q = new_Queue(sizeof(char));
  
  char in = 'a';
  char out = 'a';
  
  if(Queue_Empty(q) != TRUE) { REPORT_FAIL(); }
  for(in = 'a';in<='z';in++)
  {
    Queue_AddBack(q,&in);
  }
  if(Queue_Empty(q) != FALSE) { REPORT_FAIL(); }
  if(Queue_Size(q) != 26) { REPORT_FAIL(); }
  
  Queue_StartIterator(q);
  in = 'a';
  while(Queue_NextNode(q,&out)!=EEND && in<='z')
  {
    if(out!=in) { REPORT_FAIL(); }
    in++;
  }
      
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueIntDemo)
  int i = 0;
  Queue q = new_Queue(sizeof(int));
  
  printf("\nCreated a new int queue\n");
  Queue_intPrint(q);
  
  for(i=0;i<5;i++)
  {
    printf("Adding %d to queue\n",i);  
    Queue_AddBack(q,&i);
    Queue_intPrint(q);
  }
  
  while(!Queue_Empty(q)) 
  {
    Queue_RemoveFront(q,&i);
    printf("Removed %d from queue\n",i);
    Queue_intPrint(q);
  }
  
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueCharDemo)
  char i = 'a';
  Queue q = new_Queue(sizeof(char));
  
  printf("\nCreated a new char queue\n");
  Queue_charPrint(q);
  
  for(i='a';i<'h';i++)
  {
    printf("Adding %c to queue\n",i);  
    Queue_AddBack(q,&i);
    Queue_charPrint(q);
  }
  
  while(!Queue_Empty(q)) 
  {
    Queue_RemoveFront(q,&i);
    printf("Removed %c from queue\n",i);
    Queue_charPrint(q);
  }
  
  free_Queue(q); q = NULL;
END_TEST_DEF

START_TEST_DEF(QueueFloatDemo)
  float i = 0.2;
  Queue q = new_Queue(sizeof(float));
  
  printf("\nCreated a new float queue\n");
  Queue_floatPrint(q);
  
  for(i=1.2;i<10;i*=1.3)
  {
    printf("Adding %f to queue\n",i);  
    Queue_AddBack(q,&i);
    Queue_floatPrint(q);
  }
  
  while(!Queue_Empty(q)) 
  {
    Queue_RemoveFront(q,&i);
    printf("Removed %f from queue\n",i);
    Queue_floatPrint(q);
  }
  
  free_Queue(q); q = NULL;
END_TEST_DEF


/******************* END TEST DEFINITIONS *****************************/

/********************** MAIN THREAD ***********************************/
int main(void) 
{
  int numpassed = 0; // Number of tests passed
  numtests = 0;
  
  printf("Starting Queue tests\n\n");
   
  RUN_TEST(QueueAddFront);
  RUN_TEST(QueueRemoveBack);
  RUN_TEST(QueueClear);
  RUN_TEST(QueueGetFront);
  RUN_TEST(QueueIterate);
  RUN_TEST(QueueIntDemo);
  RUN_TEST(QueueCharDemo);
  RUN_TEST(QueueFloatDemo);
  
  printf("\n%d of %d tests passed\n",numpassed,numtests);
  if(numpassed != numtests) {
    printf("%d tests FAILED!\n",(numtests-numpassed));
  }
  
  return 0;
}
/****************** END MAIN **************************************/
